#include <ArduinoMqttClient.h>                    //MQTT传输数据
#include <WiFi101.h>                              //WiFi模块
#include <TinyGPS++.h>                            //GPS
//#include "arduino_secrets.h"
#include <DFRobot_DHT11.h>                        //使用DHT11
DFRobot_DHT11 DHT;
#define DHT11_PIN 2
#include <stdio.h>
#include <SPI.h>
#include <Arduino.h>                              
#include <wiring_private.h>                       // required before wiring_private.h
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "TP-LINK_DFB3";        // WiFi名称
char pass[] = "12345689";            // WiFi密码
WiFiClient wifiClient;               //定义一个变量
MqttClient mqttClient(wifiClient);

const char broker[] = "114.115.177.75";          //云平台地址
int        port     = 1883;                      //端口号
const char topic[]  = "COO001tepdata";           //主题名           
const char topic2[]  = "COO001locationdata";
const char topic3[]  = "COO001CO2data";
const char topiclight[] = "COO001lightonoff";
char ch[16];long hi, lo, CO2;
char lightcontral;
//set interval for sending messages (milliseconds)
const long interval = 8000;                      //八秒间歇
unsigned long previousMillis = 0;

int count = 0;
 
#define PIN_SERIAL2_RX       (1ul)                // Pin description number for PIO_SERCOM on D1
#define PIN_SERIAL2_TX       (0ul)                // Pin description number for PIO_SERCOM on D0
#define PAD_SERIAL2_TX       (UART_TX_PAD_0)      // SERCOM pad 0 TX
#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_1)    // SERCOM pad 1 RX
// Serial3 pin and pad definitions (in Arduino files Variant.h & Variant.cpp)
#define PIN_SERIAL3_RX       (5ul)                // Pin description number for PIO_SERCOM on D5
#define PIN_SERIAL3_TX       (4ul)                // Pin description number for PIO_SERCOM on D4
#define PAD_SERIAL3_TX       (UART_TX_PAD_2)      // SERCOM pad 2 TX
#define PAD_SERIAL3_RX       (SERCOM_RX_PAD_3)    // SERCOM pad 3 RX

Uart Serial2(&sercom3, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX);
//Uart Serial3(&sercom4, PIN_SERIAL3_RX, PIN_SERIAL3_TX, PAD_SERIAL3_RX, PAD_SERIAL3_TX);
TinyGPSPlus gps; 
void SERCOM3_Handler()    // Interrupt handler for SERCOM3
{
  Serial2.IrqHandler();
}


//void SERCOM4_Handler()    // Interrupt handler for SERCOM4
//{
//  Serial3.IrqHandler();
//}
unsigned char hexdata[5] = {0x64, 0x69, 0x03, 0x5E, 0x4E};

void setup() {
  static boolean state = HIGH;
  static unsigned char count = 0;
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  Serial1.begin(9600);
   
  // Start Serial for debugging on the Serial Monitor
  Serial.begin(9600);
  while (!Serial && (count < 30) )
  {
    delay(200);     // Wait for serial port to connect with timeout. Needed for native USB
    digitalWrite(6, state);
    state = !state;
    count++;
  }

  pinPeripheral(0, PIO_SERCOM);   // Assign pins 0 & 1 SERCOM functionality
  pinPeripheral(1, PIO_SERCOM);
  Serial2.begin(9600);           // Begin Serial2 

  //pinPeripheral(4, PIO_SERCOM_ALT);   // Assign pins 4 & 5 SERCOM functionality
  //pinPeripheral(5, PIO_SERCOM_ALT);
  //Serial3.begin(9600);               // Begin Serial3
  
  digitalWrite(6, HIGH);
 //显示串口初始化完成
  Serial.println("Setup Complete");
  Serial1.println("Setup Complete");
  Serial2.println("Setup Complete");
 // Serial3.println("Setup Complete");
//开始连接WiFi
   Serial.print("Attempting to connect to WPA SSID: ");    
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
//成功连接
  Serial.println("You're connected to the network");
  Serial.println();
//开始通过MQTT连接云平台
  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(broker);

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());

    while (1);
  }
//连接成功
  Serial.println("You're connected to the MQTT broker!");
  Serial.println();

  // set the message receive callback
  mqttClient.onMessage(onMqttMessage);//调用函数，订阅主题信息

  Serial.print("Subscribing to topic: ");
  Serial.println(topiclight);
  Serial.println();

  // subscribe to a topiclight
  mqttClient.subscribe(topiclight);

  // topics can be unsubscribed using:
  // mqttClient.unsubscribe(topic);

  Serial.print("Topic: ");
  Serial.println(topiclight);

  Serial.println();

}

void loop() {
  bool GPSava=0;
  static unsigned long ms = 0;
  static boolean state = HIGH;
  static unsigned char c = 0;

  mqttClient.poll();

//若serial1获得数据，读取并在串口显示
if (Serial1.available() > 0) {
    if (gps.encode(Serial1.read())) {
      if (gps.location.isValid()) {
        Serial.print(F("- latitude: "));
        Serial.println(gps.location.lat());

        Serial.print(F("- longitude: "));
        Serial.println(gps.location.lng());

        Serial.print(F("- altitude: "));
        GPSava=true;
 //       if (gps.altitude.isValid())
 //       {
  //        Serial.println(gps.altitude.meters());
  //      }
  //     else{
     
 //         Serial.println(F("INVALID"));
  //     }
      } 
      else {
        GPSava=false;                                    //若未能成功获取，串口报错
        Serial.println(F("- location: INVALID"));
      }
      Serial.println();
    }
 }


 //读取CO2的数据
  if(Serial2.available()){
 //   Serial.println("1");
    ch[0]=Serial2.read();
    //H--Serial.println("2");
    if(ch[0]==0x42)            //找到0x42开始读
      while(!Serial2.available()){
      }
      ch[1]=Serial2.read();
      if(ch[1]==0x4D){
        for (int i = 2; i < 16; i++){
           while(!Serial2.available()){
           }
           ch[i]= Serial2.read();                       
        }
          CO2 = ch[6]*256 + ch[7]; //CO2 concentration，通过计算编号为6，7得到CO2数据
          Serial.print("CO2 concentration: ");//串口输出
          Serial.print(CO2);
          Serial.println("ppm");
          
        }   
      } 
    } 
  
unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time a message was sent
    previousMillis = currentMillis;

    DHT.read(DHT11_PIN);
    //串口显示MQTT发送状态
  Serial.print("Sending message to topic: ");
  Serial.println("COO001tepdata");
  Serial.print("temp:");
  Serial.print(DHT.temperature);
  Serial.print("humi:");
  Serial.println(DHT.humidity);
  Serial.print("Sending message to topic: ");
  Serial.println("COO001CO2data");
  Serial.print(" CO2:");
  Serial.println(CO2);
   Serial.println();
  // send message, the Print interface can be used to set the message contents
  //调用函数发送信息
  mqttClient.beginMessage("COO001tepdata");//主题
  mqttClient.print(DHT.temperature);       //数据
  mqttClient.print(" ");
  mqttClient.print(DHT.humidity);          //数据
  mqttClient.endMessage();                 //发送完毕
//下面过程同上
  mqttClient.beginMessage("COO001CO2data");
  mqttClient.print(CO2);
  mqttClient.endMessage();
  //if(GPSava==true){
    mqttClient.beginMessage("COO001locationdata");
    mqttClient.print(gps.location.lat());
    mqttClient.print(" ");
    mqttClient.print(gps.location.lng());
    mqttClient.endMessage();
 //  }
  }
 }
//定义函数，订阅主题消息
 void onMqttMessage(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.println("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());//来自此主题
  Serial.print("', length ");
  Serial.print(messageSize);              //数据长度
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  while (mqttClient.available()) {
    lightcontral=(char)mqttClient.read();
    Serial.print(lightcontral);
    if(lightcontral=='1'){
      digitalWrite(7,HIGH);                 //打开路灯
      Serial.print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");//串口监测程序是否进行
    }
    else{
      digitalWrite(7,LOW);                  //关闭路灯
      Serial.print("mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm");//串口监测程序是否进行
    }
    
  }
  Serial.println();
  Serial.println();
}



  
